#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
@Time: 2018/1/4 下午2:32
@Author: CZC
@File: parse_base_worker.py
"""
import traceback

from ext.data_wrap import DataWrap
from get_annual_report_field_info import GetAnnualReportFieldInfo
from get_gsxt_field_info import GetGsxtFieldInfo
from parse_common import util
from parse_common.global_field import InfoType, Model, AnnualReportModel, PageCrawlError
from parse_common.gsxt_field import GsModel
from parse_config.common_config import province_chinese_dict, BaseConfig
from parse_config.flag import *


class ParseBaseWorker(GetGsxtFieldInfo, GetAnnualReportFieldInfo):
    def __init__(self, redis_result_handler, log):
        super(ParseBaseWorker, self).__init__()

        self.log = log
        # 初始化配置信息
        config = BaseConfig()
        self.host = config.host
        self.logfile = config.logfile
        self.target_table = config.target_table
        self.annual_report_table = config.annual_report_table
        self.is_nb_mq_open = config.is_nb_mq_open
        self.is_gs_mq_open = config.is_gs_mq_open
        self.gs_topic = config.gs_topic
        self.gs_nb_topic = config.gs_nb_topic
        self.__redis_result_handler = redis_result_handler

    # 判断实体对象是否抓取正常
    @staticmethod
    def get_crawl_page(field_item, multi=False, part=InfoType.type_list):
        """
        :param field_item:
        :param multi:
        :param part:
        :return:TRUE 返回对象数组 调用者如果需要获取页面需要单独处理,FALSE 返回具体的页面信息
        """
        if not field_item:
            return field_item

        page_list = field_item.get(part)
        # 如果是详情页则允许为None
        if part == InfoType.type_detail and not page_list:
            return page_list

        if not isinstance(page_list, list) \
                or len(page_list) <= 0:
            raise PageCrawlError("未抓取到网页,或者抓取到无效或者失败的网页")

        if len(page_list) <= 0:
            raise PageCrawlError("未抓取到网页,或者抓取到无效或者失败的网页")

        if not multi:
            return page_list[0].get(u'text')

        return page_list

    def query_offline_task(self, origin_company, item):

        if not isinstance(item, dict):
            self.log.info('参数错误: item = {item}'.format(item=item))
            return FAIL

        company = item.get('_id', None)
        if company is None:
            self.log.error('没有company_name字段: item = {item}'.format(item=item))
            return FAIL

        province = item.get('province')
        if province is None:
            self.log.error('没有省份信息: company = {}'.format(company))
            return FAIL

        self.log.info('开始解析任务...province = {province} company = {company}'.format(
            province=province, company=company))
        try:
            status = self.query_company(origin_company, item)
        except Exception as e:
            self.log.error('解析异常...')
            self.log.exception(e)
            status = FAIL

        self.log.info('完成解析任务: province = {} company = {} status = {}'.format(province, company, status))
        return status

    # 开始解析
    def query_company(self, origin_company, item):

        # 先判断抓取页面信息中是否有无效拦截页面
        # self.filter_captcha_page(item)
        if not item:
            return FAIL

        # 获得企业名称
        company = item.get('_id')
        province = item.get('province')
        province = province_chinese_dict[province]

        base_info = item.get('__{}'.format(Model.BASE_INFO))
        if base_info is None:
            self.log.error('没有基本信息: province = {province} company = {company}'.format(
                province=province, company=company))
            return FAIL

        base_info_url = self.__get_base_info_url(base_info)
        self.host = util.get_url_info(base_info_url).get('site')

        # 生成基本的in_time，u_time，省份，企业等字段
        base_info_dict = self.__build_base_info_dict(item, company, province)

        # 解析工商
        status = self.parse_gs_info(origin_company, base_info_dict, base_info_url, item)

        self.log.error('工商信息解析状态: province = {province} status = {status} company = {company}'.format(
            company=company, province=province, status=status))

        return status

    # 解析工商信息
    def parse_gs_info(self, origin_company, base_info_dict, base_info_url, item):
        all_info_dict = dict()
        all_info_dict.update(base_info_dict)
        company = all_info_dict.get('company')
        province = all_info_dict.get('province')
        in_time = all_info_dict.get('_in_time')

        # 开始解析
        all_info_dict.update(self.__parse_model(company, province, item))

        # # 判断解析属性个数是否符合要求
        # if len(all_info_dict) < MIN_GS_FIELD_NUM:
        #     raise StandardError('province = {province} company = {company} field len = {length} 工商字段过少'.format(
        #         company=company, length=len(all_info_dict), province=province))

        # 统一社会信用号处理
        self.__process_register_code(company, province, all_info_dict)

        # 存储解析信息
        return self.__store_model(origin_company, all_info_dict)

    def __store_model(self, company, all_info_dict):
        # 查找数据库中的数据做融合
        result = DataWrap.result_wrap(item=all_info_dict)
        self.__redis_result_handler.save(company, result)
        return SUCCESS

    # 初始化存储dict
    @staticmethod
    def __build_base_info_dict(item, company, province):
        u_time = util.get_now_time()
        in_time = item.get('_in_time')
        if in_time is None:
            in_time = u_time

        all_info_dict = dict(company=company,
                             _utime=u_time,
                             _in_time=in_time,
                             province=province)
        return all_info_dict

    # 解析工商各个模块
    def __parse_model(self, company, province, item):
        all_info_dict = {}

        for key, value in item.items():
            if 'info' not in key:
                continue
            if AnnualReportModel.ANNUAL_REPORT in key:
                continue

            field_info = key.replace('__', '')
            try:
                field_info_dict = eval('self.get_' + field_info)(value)
            except Exception as e:
                self.log.error('province:{province},company:{company},error-part:{value},error-info:{error}'.format(
                    company=company, error=traceback.format_exc(), province=province, value=value))
                self.log.exception(e)
                field_info_dict = {}

            all_info_dict.update(field_info_dict)

        return all_info_dict

    # 获得基本信息url
    @staticmethod
    def __get_base_info_url(base_info):
        base_info_list = base_info.get(InfoType.type_list)
        if base_info_list is None:
            return ''
        if not isinstance(base_info_list, list):
            return ''
        return base_info_list[0].get('url', '')

    # 获得按年份划分好的抓取数据
    @staticmethod
    def __get_annual_report_year_info_dict(item):
        year_info_dict = {}
        for field_name, field_info in item.items():
            if AnnualReportModel.ANNUAL_REPORT not in field_name:
                continue
            if '#' not in field_name:
                continue
            try:
                year = field_name.split('#')[1]
                annual_report_field_name = field_name.split('#')[2]
            except IndexError:
                raise IndexError('annual report filed error, company:{company}'.format(company=item.get('_id')))
            if year not in year_info_dict.keys():
                year_info_dict[year] = dict()
            year_info_dict[year][annual_report_field_name] = field_info
        return year_info_dict

    # 处理统一社会信用号
    def __process_register_code(self, company, province, all_info_dict):

        if GsModel.CODE not in all_info_dict:
            all_info_dict[GsModel.CODE] = ""
        if GsModel.REGISTERED_CODE not in all_info_dict:
            all_info_dict[GsModel.REGISTERED_CODE] = ""
        if GsModel.UNIFIED_SOCIAL_CREDIT_CODE not in all_info_dict:
            all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE] = ""

        # 去空格处理
        all_info_dict[GsModel.CODE] = all_info_dict[GsModel.CODE].strip()
        all_info_dict[GsModel.REGISTERED_CODE] = all_info_dict[GsModel.REGISTERED_CODE].strip()
        all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE] = all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE].strip()

        if all_info_dict[GsModel.CODE] == "" \
                and all_info_dict[GsModel.REGISTERED_CODE] == "" \
                and all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE] == "":
            self.log.error("当前企业没有统一社会信用号或者注册号: {province} {company}".format(
                company=company,
                province=province
            ))
            return

        # 有统一社会信用号
        if all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE] != "" \
                and all_info_dict[GsModel.CODE] == "" \
                and all_info_dict[GsModel.REGISTERED_CODE] == "":
            if len(all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE]) != 18:
                self.log.error("统一社会信用号不为18位: {province} {company}".format(
                    company=company, province=province))
            return

        # 有注册号
        if all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE] == "" \
                and all_info_dict[GsModel.CODE] == "" \
                and all_info_dict[GsModel.REGISTERED_CODE] != "":
            return

        # 如果有code 但是没有统一社会信用号 和注册号
        if all_info_dict[GsModel.CODE] != "" \
                and all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE] == "" \
                and all_info_dict[GsModel.REGISTERED_CODE] == "":
            if len(all_info_dict[GsModel.CODE]) == 18:
                all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE] = all_info_dict[GsModel.CODE]
            else:
                all_info_dict[GsModel.REGISTERED_CODE] = all_info_dict[GsModel.CODE]
            return

        if all_info_dict[GsModel.CODE] != "" \
                and all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE] != "" \
                and all_info_dict[GsModel.REGISTERED_CODE] != "":
            if len(all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE]) != 18:
                all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE] = ""
                self.log.error("{code} 统一社会信用号不为18位: {province} {company}".format(
                    code=all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE], company=company, province=province))
            return

        self.log.error("有多个注册号信息: {province} {company} {code} {re_code} {un_code}".format(
            province=province,
            company=company,
            code=all_info_dict[GsModel.CODE],
            re_code=all_info_dict[GsModel.REGISTERED_CODE],
            un_code=all_info_dict[GsModel.UNIFIED_SOCIAL_CREDIT_CODE]))
